home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Files / BlitPixie / Sources / BlitPixieDirtyRects.c < prev    next >
Encoding:
Text File  |  2000-10-06  |  13.4 KB  |  724 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. //    BlitPixieDirtyRects - zero overdraw screen blitter
  3. //
  4. //        The idea is to divide the screen into small 32x1 "dirty rects".
  5. //        A bitmap keeps track of which rects are "dirty" and thus need updating.
  6. //        User needs to add all areas that have changed since last blit.
  7. //
  8. //        NOTE: Call BlitPixieInitDirtyRects before using, or you will crash.
  9. //
  10. //    written by Anders F Björklund <afb@algonet.se>
  11. //    ©2000 afb.
  12. ///--------------------------------------------------------------------------------------
  13.  
  14. #ifndef __BLITPIXIE__
  15. #include "BlitPixieHeader.h"
  16. #endif
  17.  
  18. #include "BlitPixieAsm.h"
  19.  
  20. ///--------------------------------------------------------------------------------------
  21. //    Some conditional macros
  22. ///--------------------------------------------------------------------------------------
  23.  
  24.     // LOCAL :
  25. #if GENERATINGASM
  26. #define LOCAL extern    // generate "extern" references for asm
  27. #elif (USE_ASSEMBLY || USE_GENERIC_C)
  28. #define LOCAL static    // if we are using inline functions we can use "static"
  29. #if USE_PPC_ASSEMBLY
  30. #pragma toc_data on        // store static data in TOC directly
  31. #endif
  32. #else
  33. #define LOCAL            // if using separate functions, we need global to link
  34. #endif
  35.  
  36.     // MALLOC,FREE :
  37. #if macintosh
  38. #include <Memory.h>
  39. #define MALLOC(s)        (void *) NewPtr( s )
  40. #define FREE(p)            DisposePtr( (Ptr) p )
  41. #else
  42. #include <stdlib.h>
  43. #define MALLOC(s)        malloc(s)
  44. #define FREE(p)            free(p)
  45. #endif
  46.  
  47. ///--------------------------------------------------------------------------------------
  48. //    Local variables that store dirty rect variables
  49. ///--------------------------------------------------------------------------------------
  50.  
  51. LOCAL        unsigned char    *matrixDirtyBits;    // bitmap dirty matrix ( 1 bit = 32x1 pixels)
  52.  
  53. LOCAL        unsigned short    matrixWidth;        // width (pixels)
  54. LOCAL        unsigned short    matrixHeight;        // height (pixels)
  55. LOCAL        unsigned short    matrixDepth;        // bits per pixel
  56.  
  57. LOCAL        unsigned short    matrixBytes;        // bytes (of screen pixels)
  58. LOCAL        unsigned short    matrixRows;            // rows
  59. LOCAL        unsigned short    matrixShift;        // bit positions (in depth)
  60. LOCAL        unsigned short    matrixBits;            // pixel blocks of 32 bytes - matrix bits
  61. LOCAL        unsigned long    matrixRowBytes;        // bytes per row (in matrix)
  62.  
  63. ///--------------------------------------------------------------------------------------
  64.  
  65. #pragma mark *** PowerPC asm:
  66. #if USE_PPC_ASSEMBLY
  67.  
  68. ASM_FUNC void BlitPixieBlitClearDirtyRects(
  69.     register unsigned char    *src,        // r3
  70.     register unsigned char    *dst,        // r4
  71.     register unsigned long    color,        // r5
  72.     register unsigned long    srcBytes,    // r6
  73.     register unsigned long    dstBytes)    // r7
  74. {
  75.     #define    r_src            r3
  76.     #define    r_dst            r4
  77.     #define    r_color            r5
  78.     #define    r_srcBytes        r6
  79.     #define    r_dstBytes        r7
  80.  
  81.     #define    r_dirty            r8
  82.     #define    r_rows            r10
  83.     #define    r_rowBytes        r11
  84.     #define    r_save            r12
  85.     
  86.     ASM_BEGIN
  87.     
  88.     lwz     r_dirty,matrixDirtyBits(RTOC)
  89.     lhz     r_rows,matrixRows(RTOC)
  90.     lwz     r_rowBytes,matrixRowBytes(RTOC)
  91.  
  92.         // double background pixels (long->double)
  93.     stw        r_color,-8(SP)
  94.     stw        r_color,-4(SP)
  95.  
  96.     dcbt    r0,r_dirty
  97.         
  98.         // calculate stride from matrixRowBytes ( 8 bits per byte, 32 pixel bytes per bit)
  99.     rlwinm    r0,r_rowBytes,8,0,31-8
  100.     mfcr    r_save
  101.  
  102.     sub        r_srcBytes,r_srcBytes,r0
  103.     sub        r_dstBytes,r_dstBytes,r0
  104.  
  105.     lfd        fp0,-8(SP)
  106.     subi    r_dirty,r_dirty,1
  107.     
  108.     li        r0,0
  109. @rowloop:
  110.  
  111.     mtctr    r_rowBytes
  112.     
  113. #define MOVE_COND_32(i)        \
  114.     bc        IF_NOT,24+i,@skip##i;    \
  115.         lfd        fp1,i*32+0(r3);        \
  116.         lfd        fp2,i*32+8(r3);        \
  117.         lfd        fp3,i*32+16(r3);    \
  118.         lfd        fp4,i*32+24(r3);    \
  119.         stfd    fp0,i*32+0(r3);        \
  120.         stfd    fp0,i*32+8(r3);        \
  121.         stfd    fp0,i*32+16(r3);    \
  122.         stfd    fp0,i*32+24(r3);    \
  123.         stfd    fp1,i*32+0(r4);        \
  124.         stfd    fp2,i*32+8(r4);        \
  125.         stfd    fp3,i*32+16(r4);    \
  126.         stfd    fp4,i*32+24(r4);    \
  127. @skip##i:
  128.  
  129. @byteloop:
  130.     lbzu    r9,1(r_dirty)
  131.     cmplwi    r9,0
  132.     beq        @skipbyte
  133.  
  134.     mtcrf    0xFF,r9
  135.     stb        r0,-1(r_dirty)    //    clear matrix for next time
  136.     
  137.     MOVE_COND_32(0)
  138.     MOVE_COND_32(1)
  139.     MOVE_COND_32(2)
  140.     MOVE_COND_32(3)
  141.     MOVE_COND_32(4)
  142.     MOVE_COND_32(5)
  143.     MOVE_COND_32(6)
  144.     MOVE_COND_32(7)
  145. @skipbyte:
  146.  
  147.     addi    r3,r3,8*32
  148.     addi    r4,r4,8*32
  149.  
  150.     bdnz    @byteloop
  151.  
  152. #undef MOVE_COND_32
  153.  
  154.     subic.    r_rows,r_rows,1
  155.     
  156.     add        r3,r3,r_srcBytes
  157.     add        r4,r4,r_dstBytes
  158.  
  159.     bne        @rowloop
  160.  
  161.     mtcrf    0xFF,r_save
  162.  
  163.     ASM_END
  164. }
  165.  
  166. ASM_FUNC void BlitPixieBlitEraseDirtyRects(
  167.     register unsigned char    *src,        // r3
  168.     register unsigned char    *dst,        // r4
  169.     register unsigned char    *bkg,        // r5
  170.     register unsigned long    srcBytes,    // r6
  171.     register unsigned long    dstBytes)    // r7
  172. {
  173.     #define r_src        r3
  174.     #define r_dst        r4
  175.     #define r_bkg        r5
  176.     #define r_srcBytes    r6
  177.     #define r_dstBytes    r7
  178.  
  179.     #define    r_dirty            r8
  180.     #define    r_rows            r10
  181.     #define    r_rowBytes        r11
  182.     #define    r_save            r12
  183.  
  184.     ASM_BEGIN
  185.     
  186.     lwz     r_dirty,matrixDirtyBits(RTOC)
  187.     lhz     r_rows,matrixRows(RTOC)
  188.     lwz     r_rowBytes,matrixRowBytes(RTOC)
  189.  
  190.     dcbt    r0,r_dirty
  191.     
  192.         // calculate stride from matrixRowBytes ( 8 bits per byte, 32 pixel bytes per bit)
  193.     rlwinm    r0,r_rowBytes,8,0,31-8
  194.     mfcr    r_save
  195.  
  196.     sub        r_srcBytes,r_srcBytes,r0
  197.     sub        r_dstBytes,r_dstBytes,r0
  198.  
  199.     subi    r_dirty,r_dirty,1
  200.  
  201.     li        r0,0
  202. @rowloop:
  203.  
  204.     mtctr    r_rowBytes
  205.     
  206. #define MOVE_COND_32(i)        \
  207.     bc        IF_NOT,24+i,@skip##i;    \
  208.         lfd        fp1,i*32+0(r5);        \
  209.         lfd        fp2,i*32+8(r5);        \
  210.         lfd        fp3,i*32+16(r5);    \
  211.         lfd        fp4,i*32+24(r5);    \
  212.         lfd        fp5,i*32+0(r3);        \
  213.         lfd        fp6,i*32+8(r3);        \
  214.         lfd        fp7,i*32+16(r3);    \
  215.         lfd        fp8,i*32+24(r3);    \
  216.         stfd    fp1,i*32+0(r3);        \
  217.         stfd    fp2,i*32+8(r3);        \
  218.         stfd    fp3,i*32+16(r3);    \
  219.         stfd    fp4,i*32+24(r3);    \
  220.         stfd    fp5,i*32+0(r4);        \
  221.         stfd    fp6,i*32+8(r4);        \
  222.         stfd    fp7,i*32+16(r4);    \
  223.         stfd    fp8,i*32+24(r4);    \
  224. @skip##i:
  225.  
  226. @byteloop:
  227.     lbzu    r9,1(r_dirty)
  228.     cmplwi    r9,0
  229.     beq        @skipbyte
  230.  
  231.     mtcrf    0xFF,r9
  232.     stb        r0,-1(r_dirty)    //    clear matrix for next time
  233.     
  234.     MOVE_COND_32(0)
  235.     MOVE_COND_32(1)
  236.     MOVE_COND_32(2)
  237.     MOVE_COND_32(3)
  238.     MOVE_COND_32(4)
  239.     MOVE_COND_32(5)
  240.     MOVE_COND_32(6)
  241.     MOVE_COND_32(7)
  242. @skipbyte:
  243.  
  244.     addi    r3,r3,8*32
  245.     addi    r4,r4,8*32
  246.     addi    r5,r5,8*32
  247.  
  248.     bdnz    @byteloop
  249.  
  250. #undef MOVE_COND_32
  251.  
  252.     subic.    r_rows,r_rows,1
  253.     
  254.     add        r3,r3,r_srcBytes
  255.     add        r4,r4,r_dstBytes
  256.     add        r5,r5,r_srcBytes
  257.  
  258.     bne        @rowloop
  259.  
  260.     mtcrf    0xFF,r_save
  261.  
  262.     ASM_END
  263. }
  264.  
  265. #pragma mark *** 680X0 asm :
  266. #elif USE_68K_ASSEMBLY
  267.  
  268. ASM_FUNC void BlitPixieBlitClearDirtyRects(
  269.     unsigned char    *src,        // A0
  270.     unsigned char    *dst,        // A1
  271.     unsigned long    color,        // D0
  272.     unsigned long    srcBytes,    // D2
  273.     unsigned long    dstBytes)    // D3
  274. {
  275.     ASM_BEGIN
  276.  
  277.     MOVEM.L    D3-D7/A2,-(SP)
  278.  
  279.     MOVEM.L    src,A0/A1
  280.     MOVEM.L    srcBytes,D2-D3
  281.     CLR.L    D4
  282.     CLR.L    D5
  283.  
  284.     MOVEA.L    matrixDirtyBits,A2
  285.     MOVE.L    matrixRowBytes,D4
  286.     MOVE.W    matrixRows,D5
  287.  
  288.     MOVE.L    D4,D0
  289.     LSL.L    #8,D0
  290.     SUB.L    D0,D2
  291.     SUB.L    D0,D3
  292.  
  293.     SUBQ.W    #1,D4
  294.     SUBQ.W    #1,D5
  295.     
  296.     MOVE.L    color,D0
  297.     CLR.L    D1
  298.     MOVEQ    #32,D7
  299.         
  300. @rowloop:
  301.  
  302.     MOVE.W    D4,D6
  303.  
  304. #define MOVE_COND_32(i) \
  305.     LSL.B    #1,D1;                \
  306.     BCC.S    @skip##i;            \
  307.     MOVE.L    (A0),(A1)+;            \
  308.     MOVE.L    D0,(A0)+;            \
  309.     MOVE.L    (A0),(A1)+;            \
  310.     MOVE.L    D0,(A0)+;            \
  311.     MOVE.L    (A0),(A1)+;            \
  312.     MOVE.L    D0,(A0)+;            \
  313.     MOVE.L    (A0),(A1)+;            \
  314.     MOVE.L    D0,(A0)+;            \
  315.     MOVE.L    (A0),(A1)+;            \
  316.     MOVE.L    D0,(A0)+;            \
  317.     MOVE.L    (A0),(A1)+;            \
  318.     MOVE.L    D0,(A0)+;            \
  319.     MOVE.L    (A0),(A1)+;            \
  320.     MOVE.L    D0,(A0)+;            \
  321.     MOVE.L    (A0),(A1)+;            \
  322.     MOVE.L    D0,(A0)+;            \
  323.     BRA.S    @end##i;            \
  324. @skip##i:                        \
  325.     ADDA.L    D7,A0;                \
  326.     ADDA.L    D7,A1;                \
  327. @end##i:
  328.  
  329. @byteloop:
  330.     MOVE.B    (A2),D1
  331.     BEQ        @skipbyte
  332.     CLR.B    (A2)+            //    clear matrix for next time
  333.  
  334.     MOVE_COND_32(0)
  335.     MOVE_COND_32(1)
  336.     MOVE_COND_32(2)
  337.     MOVE_COND_32(3)
  338.     MOVE_COND_32(4)
  339.     MOVE_COND_32(5)
  340.     MOVE_COND_32(6)
  341.     MOVE_COND_32(7)
  342.  
  343.     DBRA    D6,@byteloop
  344.     BRA        @nextrow
  345.  
  346. #undef MOVE_COND_32
  347.  
  348. @skipbyte:
  349.     MOVE.B    #32*8-1,D1
  350.     ADDA.L    D1,A0
  351.     ADDA.L    D1,A1
  352.     ADDQ.L    #1,A0
  353.     ADDQ.L    #1,A1
  354.     ADDQ.L    #1,A2
  355.  
  356.     DBRA    D6,@byteloop
  357.  
  358. @nextrow:
  359.     ADDA.L    D2,A0
  360.     ADDA.L    D3,A1
  361.  
  362.     DBRA    D5,@rowloop
  363.  
  364.     MOVEM.L    (SP)+,D3-D7/A2
  365.  
  366.     ASM_END
  367. }
  368.  
  369. ASM_FUNC void BlitPixieBlitEraseDirtyRects(
  370.     unsigned char    *src,
  371.     unsigned char    *dst,
  372.     unsigned char    *bkg,
  373.     unsigned long    srcBytes,
  374.     unsigned long    dstBytes)
  375. {
  376.     ASM_BEGIN
  377.  
  378.     MOVEM.L    D3-D7/A2-A3,-(SP)
  379.  
  380.     MOVEM.L    src,A0-A2
  381.     MOVEM.L    srcBytes,D2-D3
  382.     CLR.L    D4
  383.     CLR.L    D5
  384.  
  385.     MOVEA.L    matrixDirtyBits,A3
  386.     MOVE.L    matrixRowBytes,D4
  387.     MOVE.W    matrixRows,D5
  388.  
  389.     MOVE.L    D4,D0
  390.     LSL.L    #8,D0
  391.     SUB.L    D0,D2
  392.     SUB.L    D0,D3
  393.  
  394.     SUBQ.W    #1,D4
  395.     SUBQ.W    #1,D5
  396.  
  397.     CLR.L    D1
  398.     MOVEQ    #32,D7
  399.  
  400. @rowloop:
  401.  
  402.     MOVE.W    D4,D6
  403.  
  404. #define MOVE_COND_32(i) \
  405.     LSL.B    #1,D1;                \
  406.     BCC.S    @skip##i;            \
  407.     MOVE.L    (A0),(A1)+;            \
  408.     MOVE.L    (A2)+,(A0)+;        \
  409.     MOVE.L    (A0),(A1)+;            \
  410.     MOVE.L    (A2)+,(A0)+;        \
  411.     MOVE.L    (A0),(A1)+;            \
  412.     MOVE.L    (A2)+,(A0)+;        \
  413.     MOVE.L    (A0),(A1)+;            \
  414.     MOVE.L    (A2)+,(A0)+;        \
  415.     MOVE.L    (A0),(A1)+;            \
  416.     MOVE.L    (A2)+,(A0)+;        \
  417.     MOVE.L    (A0),(A1)+;            \
  418.     MOVE.L    (A2)+,(A0)+;        \
  419.     MOVE.L    (A0),(A1)+;            \
  420.     MOVE.L    (A2)+,(A0)+;        \
  421.     MOVE.L    (A0),(A1)+;            \
  422.     MOVE.L    (A2)+,(A0)+;        \
  423.     BRA.S    @end##i;            \
  424. @skip##i:                        \
  425.     ADDA.L    D7,A0;                \
  426.     ADDA.L    D7,A1;                \
  427.     ADDA.L    D7,A2;                \
  428. @end##i:
  429.  
  430. @byteloop:
  431.     MOVE.B    (A3),D1
  432.     BEQ        @skipbyte
  433.     CLR.B    (A3)+            //    clear matrix for next time
  434.  
  435.     MOVE_COND_32(0)
  436.     MOVE_COND_32(1)
  437.     MOVE_COND_32(2)
  438.     MOVE_COND_32(3)
  439.     MOVE_COND_32(4)
  440.     MOVE_COND_32(5)
  441.     MOVE_COND_32(6)
  442.     MOVE_COND_32(7)
  443.  
  444.     DBRA    D6,@byteloop
  445.     BRA        @nextrow
  446.     
  447. #undef MOVE_COND_32
  448.  
  449. @skipbyte:
  450.     MOVE.B    #32*8-1,D1
  451.     ADDA.L    D1,A0
  452.     ADDA.L    D1,A1
  453.     ADDA.L    D1,A2
  454.     ADDQ.L    #1,A0
  455.     ADDQ.L    #1,A1
  456.     ADDQ.L    #1,A2
  457.     ADDQ.L    #1,A3
  458.  
  459.     DBRA    D6,@byteloop
  460.  
  461. @nextrow:
  462.     ADDA.L    D2,A0
  463.     ADDA.L    D3,A1
  464.     ADDA.L    D2,A2
  465.     
  466.     DBRA    D5,@rowloop
  467.  
  468.     MOVEM.L    (SP)+,D3-D7/A2-A3
  469.  
  470.     ASM_END
  471. }
  472.  
  473. #pragma mark *** Generic C :
  474. #elif USE_GENERIC_C
  475.  
  476. void BlitPixieBlitClearDirtyRects(
  477.     unsigned char    *src,
  478.     unsigned char    *dst,
  479.     unsigned long    color,
  480.     unsigned long    srcBytes,
  481.     unsigned long    dstBytes)
  482. {
  483.     int                x,y;
  484.     unsigned char    *p,*row;
  485.     unsigned int    c,m;
  486.  
  487.     srcBytes -= matrixBytes;
  488.     dstBytes -= matrixBytes;
  489.  
  490.     row = matrixDirtyBits;
  491.     for ( y = 0; y < matrixRows; y++ )
  492.     {
  493.         p = row;
  494.         m = 0;
  495.         
  496.         for ( x = 0; x < matrixBits; x++ )
  497.         {
  498.             if ( m == 0 )
  499.             {
  500.                 m = 0x80;
  501.                 c = *p;
  502.                 *p++ = 0;
  503.             }
  504.             
  505.             if ( c & m )
  506.             {
  507.                     // copy offscreen->screen
  508.                 BlitPixieMemCopy( dst, src, 32 );
  509.                     // clear offscreen
  510.                 BlitPixieMemSet( src, color, 32 );
  511.             }
  512.             
  513.             src += 32;
  514.             dst += 32;
  515.         
  516.             m >>= 1;
  517.         }
  518.  
  519.         src += srcBytes;
  520.         dst += dstBytes;
  521.     
  522.         row += matrixRowBytes;
  523.     }
  524. }
  525.  
  526. void BlitPixieBlitEraseDirtyRects(
  527.     unsigned char    *src,
  528.     unsigned char    *dst,
  529.     unsigned char    *bkg,
  530.     unsigned long    srcBytes,
  531.     unsigned long    dstBytes)
  532. {
  533.     int                x,y;
  534.     unsigned char    *p,*row;
  535.     unsigned int    c,m;
  536.  
  537.     srcBytes -= matrixBytes;
  538.     dstBytes -= matrixBytes;
  539.  
  540.     row = matrixDirtyBits;
  541.     for ( y = 0; y < matrixRows; y++ )
  542.     {
  543.         p = row;
  544.         m = 0;
  545.         
  546.         for ( x = 0; x < matrixBits; x++ )
  547.         {
  548.             if ( m == 0 )
  549.             {
  550.                 m = 0x80;
  551.                 c = *p;
  552.                 *p++ = 0;
  553.             }
  554.             
  555.             if ( c & m )
  556.             {
  557.                     // copy offscreen->screen
  558.                 BlitPixieMemCopy( dst, src, 32 );
  559.                     // erase offscreen
  560.                 BlitPixieMemCopy( src, bkg, 32 );
  561.             }
  562.                 
  563.             src += 32;
  564.             dst += 32;
  565.             bkg += 32;
  566.         
  567.             m >>= 1;
  568.         }
  569.  
  570.         src += srcBytes;
  571.         dst += dstBytes;
  572.         bkg += srcBytes;
  573.         
  574.         row += matrixRowBytes;
  575.     }
  576. }
  577.  
  578. #endif
  579.  
  580. #pragma mark -
  581. // ————————————————————————————————————————————————————————————————————————————————
  582.  
  583. #ifndef GENERATINGASM // do not include for asm file generation
  584.  
  585. Boolean BlitPixieInitDirtyRects( unsigned char *src, unsigned char *dst,
  586.     unsigned short width, unsigned short height, unsigned short depth  )
  587. {
  588.     long    bytes;
  589.     
  590.     bytes = ( width * depth ) >> 3;
  591.  
  592.     if ( depth != 8 && depth != 16 && depth != 32 )
  593.     {
  594.         BLITPIXIE_DEBUGGER("DirtyRects: depth must be 8, 16 or 32");
  595.         return false;
  596.     }
  597.  
  598.     if ( (bytes & 31) != 0 )
  599.     {
  600.         BLITPIXIE_DEBUGGER("DirtyRects: bytes must be multiple of 32");
  601.         return false;
  602.     }
  603.  
  604.     if ( (((unsigned long) src) & 3) != 0 || (((unsigned long) dst) & 3) != 0)
  605.     {
  606.         BLITPIXIE_DEBUGGER("DirtyRects: src and dst must be aligned");
  607.         return false;
  608.     }
  609.     
  610.     matrixWidth = width;
  611.     matrixHeight = height;
  612.     matrixDepth = depth;
  613.  
  614.     matrixBytes = bytes;
  615.     matrixRows = height;
  616.  
  617.     matrixShift = matrixDepth >> 4;
  618.     matrixBits = matrixBytes >> 5;
  619.     matrixRowBytes = (matrixBits + 7) >> 3;
  620.  
  621.     matrixDirtyBits = (unsigned char *) MALLOC(matrixRowBytes * matrixRows);
  622.     if ( matrixDirtyBits == NULL )
  623.     {
  624.         BLITPIXIE_DEBUGGER("DirtyRects: Couldn't get dirty matrix mem!");
  625.         return false;
  626.     }
  627.  
  628.     BlitPixieClearDirtyRects();
  629.     BlitPixieAddDirtyRect( (Rect*) NULL );
  630.  
  631.     return true;
  632. }
  633.  
  634.  
  635. void BlitPixieExitDirtyRects(void)
  636. {
  637.     if ( matrixDirtyBits )
  638.     {
  639.         FREE(matrixDirtyBits);
  640.         matrixDirtyBits = NULL;
  641.     }
  642. }
  643.  
  644.  
  645. void BlitPixieAddDirtyRect( Rect *dirtyRect )
  646. {
  647.     long                top,left,bottom,right;
  648.     long                startBit,stopBit;
  649.     long                y,bit,grid;
  650.     unsigned char        *row,*p;
  651.     unsigned char        m;
  652.     
  653.     if ( dirtyRect != NULL )
  654.     {
  655.         top = dirtyRect->top;
  656.         left = dirtyRect->left;
  657.         bottom = dirtyRect->bottom;
  658.         right = dirtyRect->right;
  659.  
  660.         //    align to 32-byte grid
  661.         grid = 32 >> matrixShift;
  662.         left = (left) & ~(grid - 1);
  663.         right = (right + grid - 1) & ~(grid - 1);
  664.  
  665.         //    clip
  666.         if ( left < 0 )                    left = 0;
  667.         if ( top < 0 )                    top = 0;
  668.         if ( right >= matrixWidth )        right = matrixWidth - 1;
  669.         if ( bottom >= matrixHeight )    bottom = matrixHeight - 1;
  670.  
  671.         //    check for empty/clipped rect
  672.         if ( left >= right )    return;
  673.         if ( top >= bottom )    return;
  674.     }
  675.     else
  676.     {
  677.             // add whole area
  678.         left = 0;
  679.         top = 0;
  680.         right = matrixWidth - 1;
  681.         bottom = matrixHeight - 1;
  682.     }
  683.     
  684.     //    pixels to bytes
  685.     left <<= matrixShift;
  686.     right <<= matrixShift;
  687.     
  688.     //    calculate bit mask
  689.     startBit = left >> 5;
  690.     stopBit = right >> 5;
  691.  
  692.     //    add to dirty matrix (set bits)
  693.     y = bottom - top;
  694.     row = matrixDirtyBits + (top * matrixRowBytes);
  695.     while (y--)
  696.     {
  697.         p = row + (startBit >> 3);
  698.         m = 0x80U >> (startBit & 7);
  699.         
  700.         for ( bit = startBit; bit <= stopBit; bit++ )
  701.         {
  702.             *p |= m;
  703.                 
  704.             m >>= 1;
  705.             if ( m == 0)
  706.             {
  707.                 p++;
  708.                 m = 0x80U;
  709.             }    
  710.         }
  711.         row += matrixRowBytes;
  712.     }
  713.  
  714. }
  715.  
  716. void BlitPixieClearDirtyRects( void )
  717. {
  718.         // clear all bits in dirty matrix
  719.     BlitPixieMemSet(matrixDirtyBits,0L, matrixRowBytes * matrixRows);
  720. }
  721.  
  722.  
  723. #endif // GENERATINGASM
  724.